<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1265279
-->

<head>
  <meta charset="utf-8">
  <title>Test for Bug 1309099 - Web Manifest: Implement window.onappinstalled</title>
  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
  <script>
  "use strict";
  SimpleTest.waitForExplicitFinish();
  const finish = SimpleTest.finish.bind(SimpleTest);
  enableOnAppInstalledPref()
    .then(createIframe)
    .then(checkImplementation)
    .then(checkOnappInstalledEventFired)
    .then(checkAddEventListenerFires)
    .then(finish)
    .catch(err => {
      ok(false, err.stack);
      finish();
    });

  function enableOnAppInstalledPref() {
    const ops = {
      "set": [
        ["dom.manifest.onappinstalled", true],
      ],
    };
    return SpecialPowers.pushPrefEnv(ops);
  }

  // WebIDL conditional annotations for an interface are evaluate once per
  // global, so we need to create an iframe to see the effects of calling
  // enableOnAppInstalledPref().
  function createIframe() {
    return new Promise((resolve) => {
      const iframe = document.createElement("iframe");
      iframe.src = "about:blank";
      iframe.onload = () => resolve(iframe.contentWindow);
      document.body.appendChild(iframe);
    });
  }

  // Check that the WebIDL is as expected.
  function checkImplementation(ifrWindow) {
    return new Promise((resolve, reject) => {
      const hasOnAppInstalledProp = ifrWindow.hasOwnProperty("onappinstalled");
      ok(hasOnAppInstalledProp, "window has own onappinstalled property");

      // no point in continuing
      if (!hasOnAppInstalledProp) {
        const err = new Error("No 'onappinstalled' IDL attribute. Aborting early.");
        return reject(err);
      }
      is(ifrWindow.onappinstalled, null, "window install is initially set to null");

      // Check that enumerable, configurable, and has a getter and setter.
      const objDescriptor = Object.getOwnPropertyDescriptor(ifrWindow, "onappinstalled");
      ok(objDescriptor.enumerable, "is enumerable");
      ok(objDescriptor.configurable, "is configurable");
      ok(objDescriptor.hasOwnProperty("get"), "has getter");
      ok(objDescriptor.hasOwnProperty("set"), "has setter");
      resolve(ifrWindow);
    });
  }

  // Checks that .onappinstalled receives an event.
  function checkOnappInstalledEventFired(ifrWindow) {
    const customEv = new CustomEvent("appinstalled");
    return new Promise((resolve) => {
      // Test is we receive the event on `appinstalled`
      ifrWindow.onappinstalled = ev => {
        ifrWindow.onappinstalled = null;
        is(ev, customEv, "The events should be the same event object");
        resolve(ifrWindow);
      };
      ifrWindow.dispatchEvent(customEv);
    });
  }

  // Checks that .addEventListener("appinstalled") receives an event.
  function checkAddEventListenerFires(ifrWindow) {
    const customEv = new CustomEvent("appinstalled");
    return new Promise((resolve) => {
      ifrWindow.addEventListener("appinstalled", function handler(ev) {
        ifrWindow.removeEventListener("appinstalled", handler);
        is(ev, customEv, "The events should be the same");
        resolve(ifrWindow);
      });
      ifrWindow.dispatchEvent(customEv);
    });
  }
  </script>
</head>
